{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "import metadsl.nonumpy.compat as np\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "e = np.array((1, 2, 3), ndmin=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "metadsl.python.compat.Integer"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(e.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "from metadsl.expressions import Expression\n",
    "\n",
    "def as_tuple_with_type(expr):\n",
    "    return Expression.from_instance(expr).fold(\n",
    "        lambda expr: (dataclasses.astuple(expr.type), expr.value),\n",
    "        lambda call: (call.function.__name__,) + tuple(call.args),\n",
    "        lambda value: value\n",
    "    )\n",
    "\n",
    "def as_tuple(expr):\n",
    "    return Expression.from_instance(expr).fold(\n",
    "        lambda expr: expr.value,\n",
    "        lambda call: (call.function,) + tuple(call.args),\n",
    "        lambda value: value\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('__getitem__',\n",
       " ('shape',\n",
       "  ('array',\n",
       "   (1, 2, 3),\n",
       "   ('create_none_call',),\n",
       "   True,\n",
       "   ('create_none_call',),\n",
       "   ('create_none_call',),\n",
       "   ('create_some', 2))),\n",
       " 0)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "as_tuple(e)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((metadsl.nonumpy.compat.NDArray, ()),\n",
       " ('__add__',\n",
       "  ((metadsl.nonumpy.pure.NDArray, ()),\n",
       "   ('arange',\n",
       "    ((metadsl.python.pure.Optional, ((metadsl.python.compat.Number, ()),)),\n",
       "     ('create_none_call',)),\n",
       "    ((metadsl.python.pure.Number, ()), 10),\n",
       "    ((metadsl.python.pure.Optional, ((metadsl.python.compat.Number, ()),)),\n",
       "     ('create_none_call',)),\n",
       "    ((metadsl.python.pure.Optional, ((metadsl.nonumpy.pure.DType, ()),)),\n",
       "     ('create_none_call',)))),\n",
       "  ((metadsl.nonumpy.pure.NDArray, ()), 10)))"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "as_tuple_with_type(np.arange(10) + 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = np.arange(10) < np.arange(10, 100, dtype='int64') + np.arange(10)\n",
    "\n",
    "# execute_uarray(x, backend=unumpy.backends.torch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import unumpy\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "import metadsl.expressions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "@metadsl.expressions.call(lambda a, b: a)(unumpy.arange)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(<function __main__.some_random_function(a, b)>,\n",
       " (<function metadsl.nonumpy.pure.NDArray.__lt__(self, other: 'NDArray') -> 'NDArray'>,\n",
       "  (<function metadsl.nonumpy.pure.arange(start: metadsl.python.pure.Optional[metadsl.python.pure.Number], stop: metadsl.python.pure.Number, step: metadsl.python.pure.Optional[metadsl.python.pure.Number], dtype: metadsl.python.pure.Optional[metadsl.nonumpy.pure.DType]) -> metadsl.nonumpy.pure.NDArray>,\n",
       "   (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "   10,\n",
       "   (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "   (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,)),\n",
       "  (<function metadsl.nonumpy.pure.NDArray.__add__(self, other: 'NDArray') -> 'NDArray'>,\n",
       "   (<function metadsl.nonumpy.pure.arange(start: metadsl.python.pure.Optional[metadsl.python.pure.Number], stop: metadsl.python.pure.Number, step: metadsl.python.pure.Optional[metadsl.python.pure.Number], dtype: metadsl.python.pure.Optional[metadsl.nonumpy.pure.DType]) -> metadsl.nonumpy.pure.NDArray>,\n",
       "    (<function metadsl.python.pure.Optional.create_some(value: ~T) -> 'Optional[T]'>,\n",
       "     10),\n",
       "    100,\n",
       "    (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "    (<function metadsl.python.pure.Optional.create_some(value: ~T) -> 'Optional[T]'>,\n",
       "     'int64')),\n",
       "   (<function metadsl.nonumpy.pure.arange(start: metadsl.python.pure.Optional[metadsl.python.pure.Number], stop: metadsl.python.pure.Number, step: metadsl.python.pure.Optional[metadsl.python.pure.Number], dtype: metadsl.python.pure.Optional[metadsl.nonumpy.pure.DType]) -> metadsl.nonumpy.pure.NDArray>,\n",
       "    (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "    10,\n",
       "    (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "    (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,)))),\n",
       " (<function metadsl.nonumpy.pure.NDArray.__lt__(self, other: 'NDArray') -> 'NDArray'>,\n",
       "  (<function metadsl.nonumpy.pure.arange(start: metadsl.python.pure.Optional[metadsl.python.pure.Number], stop: metadsl.python.pure.Number, step: metadsl.python.pure.Optional[metadsl.python.pure.Number], dtype: metadsl.python.pure.Optional[metadsl.nonumpy.pure.DType]) -> metadsl.nonumpy.pure.NDArray>,\n",
       "   (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "   10,\n",
       "   (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "   (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,)),\n",
       "  (<function metadsl.nonumpy.pure.NDArray.__add__(self, other: 'NDArray') -> 'NDArray'>,\n",
       "   (<function metadsl.nonumpy.pure.arange(start: metadsl.python.pure.Optional[metadsl.python.pure.Number], stop: metadsl.python.pure.Number, step: metadsl.python.pure.Optional[metadsl.python.pure.Number], dtype: metadsl.python.pure.Optional[metadsl.nonumpy.pure.DType]) -> metadsl.nonumpy.pure.NDArray>,\n",
       "    (<function metadsl.python.pure.Optional.create_some(value: ~T) -> 'Optional[T]'>,\n",
       "     10),\n",
       "    100,\n",
       "    (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "    (<function metadsl.python.pure.Optional.create_some(value: ~T) -> 'Optional[T]'>,\n",
       "     'int64')),\n",
       "   (<function metadsl.nonumpy.pure.arange(start: metadsl.python.pure.Optional[metadsl.python.pure.Number], stop: metadsl.python.pure.Number, step: metadsl.python.pure.Optional[metadsl.python.pure.Number], dtype: metadsl.python.pure.Optional[metadsl.nonumpy.pure.DType]) -> metadsl.nonumpy.pure.NDArray>,\n",
       "    (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "    10,\n",
       "    (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "    (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,)))))"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "as_tuple(some_random_function(x, x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "os.environ['NUMPY_EXPERIMENTAL_ARRAY_FUNCTION'] = '1'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as real_np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "invalid entry 0 in condlist: should be boolean ndarray",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-25-3badab716b58>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mreal_np\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mselect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/usr/local/miniconda3/envs/metadsl/lib/python3.7/site-packages/numpy/lib/function_base.py\u001b[0m in \u001b[0;36mselect\u001b[0;34m(condlist, choicelist, default)\u001b[0m\n\u001b[1;32m    713\u001b[0m             \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    714\u001b[0m                 raise ValueError(\n\u001b[0;32m--> 715\u001b[0;31m                     'invalid entry {} in condlist: should be boolean ndarray'.format(i))\n\u001b[0m\u001b[1;32m    716\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    717\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mdeprecated_ints\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mValueError\u001b[0m: invalid entry 0 in condlist: should be boolean ndarray"
     ]
    }
   ],
   "source": [
    "real_np.select([np.arange(10)], [np.arange(10)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(<function metadsl.nonumpy.pure.NDArray.__array_ufunc__(ufunc: 'UFunc', method: 'UFuncMethod', kwargs: 'UFuncKwargs', *inputs: 'NDArray') -> 'NDArray'>,\n",
       " <ufunc 'multiply'>,\n",
       " 'outer',\n",
       " (),\n",
       " (<function metadsl.nonumpy.pure.arange(start: metadsl.python.pure.Optional[metadsl.python.pure.Number], stop: metadsl.python.pure.Number, step: metadsl.python.pure.Optional[metadsl.python.pure.Number], dtype: metadsl.python.pure.Optional[metadsl.nonumpy.pure.DType]) -> metadsl.nonumpy.pure.NDArray>,\n",
       "  (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "  10,\n",
       "  (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "  (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,)),\n",
       " (<function metadsl.nonumpy.pure.arange(start: metadsl.python.pure.Optional[metadsl.python.pure.Number], stop: metadsl.python.pure.Number, step: metadsl.python.pure.Optional[metadsl.python.pure.Number], dtype: metadsl.python.pure.Optional[metadsl.nonumpy.pure.DType]) -> metadsl.nonumpy.pure.NDArray>,\n",
       "  (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "  10,\n",
       "  (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,),\n",
       "  (<bound method Optional.create_none_call of <class 'metadsl.python.pure.Optional'>>,)))"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "as_tuple(real_np.multiply.outer(np.arange(10), np.arange(10)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "metadsl.nonumpy.compat.NDArray"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(np.arange(10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "import types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((1, 2),)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tuple({1: 2}.items())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
